/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package carstoredb.models;

import carstoredb.models.exceptions.NonexistentEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author wuhao
 */
public class CarstoreJpaController implements Serializable {

	public CarstoreJpaController(EntityManagerFactory emf) {
		this.emf = emf;
	}
	private EntityManagerFactory emf = null;

	public EntityManager getEntityManager() {
		return emf.createEntityManager();
	}

	public void create(Carstore carstore) {
		if (carstore.getOrderInfoCollection() == null) {
			carstore.setOrderInfoCollection(new ArrayList<OrderInfo>());
		}
		if (carstore.getStoreInfoCollection() == null) {
			carstore.setStoreInfoCollection(new ArrayList<StoreInfo>());
		}
		EntityManager em = null;
		try {
			em = getEntityManager();
			em.getTransaction().begin();
			Collection<OrderInfo> attachedOrderInfoCollection = new ArrayList<OrderInfo>();
			for (OrderInfo orderInfoCollectionOrderInfoToAttach : carstore.getOrderInfoCollection()) {
				orderInfoCollectionOrderInfoToAttach = em.getReference(orderInfoCollectionOrderInfoToAttach.getClass(), orderInfoCollectionOrderInfoToAttach.getOrderId());
				attachedOrderInfoCollection.add(orderInfoCollectionOrderInfoToAttach);
			}
			carstore.setOrderInfoCollection(attachedOrderInfoCollection);
			Collection<StoreInfo> attachedStoreInfoCollection = new ArrayList<StoreInfo>();
			for (StoreInfo storeInfoCollectionStoreInfoToAttach : carstore.getStoreInfoCollection()) {
				storeInfoCollectionStoreInfoToAttach = em.getReference(storeInfoCollectionStoreInfoToAttach.getClass(), storeInfoCollectionStoreInfoToAttach.getId());
				attachedStoreInfoCollection.add(storeInfoCollectionStoreInfoToAttach);
			}
			carstore.setStoreInfoCollection(attachedStoreInfoCollection);
			em.persist(carstore);
			for (OrderInfo orderInfoCollectionOrderInfo : carstore.getOrderInfoCollection()) {
				Carstore oldStoreIdOfOrderInfoCollectionOrderInfo = orderInfoCollectionOrderInfo.getStoreId();
				orderInfoCollectionOrderInfo.setStoreId(carstore);
				orderInfoCollectionOrderInfo = em.merge(orderInfoCollectionOrderInfo);
				if (oldStoreIdOfOrderInfoCollectionOrderInfo != null) {
					oldStoreIdOfOrderInfoCollectionOrderInfo.getOrderInfoCollection().remove(orderInfoCollectionOrderInfo);
					oldStoreIdOfOrderInfoCollectionOrderInfo = em.merge(oldStoreIdOfOrderInfoCollectionOrderInfo);
				}
			}
			for (StoreInfo storeInfoCollectionStoreInfo : carstore.getStoreInfoCollection()) {
				Carstore oldStoreIdOfStoreInfoCollectionStoreInfo = storeInfoCollectionStoreInfo.getStoreId();
				storeInfoCollectionStoreInfo.setStoreId(carstore);
				storeInfoCollectionStoreInfo = em.merge(storeInfoCollectionStoreInfo);
				if (oldStoreIdOfStoreInfoCollectionStoreInfo != null) {
					oldStoreIdOfStoreInfoCollectionStoreInfo.getStoreInfoCollection().remove(storeInfoCollectionStoreInfo);
					oldStoreIdOfStoreInfoCollectionStoreInfo = em.merge(oldStoreIdOfStoreInfoCollectionStoreInfo);
				}
			}
			em.getTransaction().commit();
		} finally {
			if (em != null) {
				em.close();
			}
		}
	}

	public void edit(Carstore carstore) throws NonexistentEntityException, Exception {
		EntityManager em = null;
		try {
			em = getEntityManager();
			em.getTransaction().begin();
			Carstore persistentCarstore = em.find(Carstore.class, carstore.getStoreId());
			Collection<OrderInfo> orderInfoCollectionOld = persistentCarstore.getOrderInfoCollection();
			Collection<OrderInfo> orderInfoCollectionNew = carstore.getOrderInfoCollection();
			Collection<StoreInfo> storeInfoCollectionOld = persistentCarstore.getStoreInfoCollection();
			Collection<StoreInfo> storeInfoCollectionNew = carstore.getStoreInfoCollection();
			Collection<OrderInfo> attachedOrderInfoCollectionNew = new ArrayList<OrderInfo>();
			for (OrderInfo orderInfoCollectionNewOrderInfoToAttach : orderInfoCollectionNew) {
				orderInfoCollectionNewOrderInfoToAttach = em.getReference(orderInfoCollectionNewOrderInfoToAttach.getClass(), orderInfoCollectionNewOrderInfoToAttach.getOrderId());
				attachedOrderInfoCollectionNew.add(orderInfoCollectionNewOrderInfoToAttach);
			}
			orderInfoCollectionNew = attachedOrderInfoCollectionNew;
			carstore.setOrderInfoCollection(orderInfoCollectionNew);
			Collection<StoreInfo> attachedStoreInfoCollectionNew = new ArrayList<StoreInfo>();
			for (StoreInfo storeInfoCollectionNewStoreInfoToAttach : storeInfoCollectionNew) {
				storeInfoCollectionNewStoreInfoToAttach = em.getReference(storeInfoCollectionNewStoreInfoToAttach.getClass(), storeInfoCollectionNewStoreInfoToAttach.getId());
				attachedStoreInfoCollectionNew.add(storeInfoCollectionNewStoreInfoToAttach);
			}
			storeInfoCollectionNew = attachedStoreInfoCollectionNew;
			carstore.setStoreInfoCollection(storeInfoCollectionNew);
			carstore = em.merge(carstore);
			for (OrderInfo orderInfoCollectionOldOrderInfo : orderInfoCollectionOld) {
				if (!orderInfoCollectionNew.contains(orderInfoCollectionOldOrderInfo)) {
					orderInfoCollectionOldOrderInfo.setStoreId(null);
					orderInfoCollectionOldOrderInfo = em.merge(orderInfoCollectionOldOrderInfo);
				}
			}
			for (OrderInfo orderInfoCollectionNewOrderInfo : orderInfoCollectionNew) {
				if (!orderInfoCollectionOld.contains(orderInfoCollectionNewOrderInfo)) {
					Carstore oldStoreIdOfOrderInfoCollectionNewOrderInfo = orderInfoCollectionNewOrderInfo.getStoreId();
					orderInfoCollectionNewOrderInfo.setStoreId(carstore);
					orderInfoCollectionNewOrderInfo = em.merge(orderInfoCollectionNewOrderInfo);
					if (oldStoreIdOfOrderInfoCollectionNewOrderInfo != null && !oldStoreIdOfOrderInfoCollectionNewOrderInfo.equals(carstore)) {
						oldStoreIdOfOrderInfoCollectionNewOrderInfo.getOrderInfoCollection().remove(orderInfoCollectionNewOrderInfo);
						oldStoreIdOfOrderInfoCollectionNewOrderInfo = em.merge(oldStoreIdOfOrderInfoCollectionNewOrderInfo);
					}
				}
			}
			for (StoreInfo storeInfoCollectionOldStoreInfo : storeInfoCollectionOld) {
				if (!storeInfoCollectionNew.contains(storeInfoCollectionOldStoreInfo)) {
					storeInfoCollectionOldStoreInfo.setStoreId(null);
					storeInfoCollectionOldStoreInfo = em.merge(storeInfoCollectionOldStoreInfo);
				}
			}
			for (StoreInfo storeInfoCollectionNewStoreInfo : storeInfoCollectionNew) {
				if (!storeInfoCollectionOld.contains(storeInfoCollectionNewStoreInfo)) {
					Carstore oldStoreIdOfStoreInfoCollectionNewStoreInfo = storeInfoCollectionNewStoreInfo.getStoreId();
					storeInfoCollectionNewStoreInfo.setStoreId(carstore);
					storeInfoCollectionNewStoreInfo = em.merge(storeInfoCollectionNewStoreInfo);
					if (oldStoreIdOfStoreInfoCollectionNewStoreInfo != null && !oldStoreIdOfStoreInfoCollectionNewStoreInfo.equals(carstore)) {
						oldStoreIdOfStoreInfoCollectionNewStoreInfo.getStoreInfoCollection().remove(storeInfoCollectionNewStoreInfo);
						oldStoreIdOfStoreInfoCollectionNewStoreInfo = em.merge(oldStoreIdOfStoreInfoCollectionNewStoreInfo);
					}
				}
			}
			em.getTransaction().commit();
		} catch (Exception ex) {
			String msg = ex.getLocalizedMessage();
			if (msg == null || msg.length() == 0) {
				Integer id = carstore.getStoreId();
				if (findCarstore(id) == null) {
					throw new NonexistentEntityException("The carstore with id " + id + " no longer exists.");
				}
			}
			throw ex;
		} finally {
			if (em != null) {
				em.close();
			}
		}
	}

	public void destroy(Integer id) throws NonexistentEntityException {
		EntityManager em = null;
		try {
			em = getEntityManager();
			em.getTransaction().begin();
			Carstore carstore;
			try {
				carstore = em.getReference(Carstore.class, id);
				carstore.getStoreId();
			} catch (EntityNotFoundException enfe) {
				throw new NonexistentEntityException("The carstore with id " + id + " no longer exists.", enfe);
			}
			Collection<OrderInfo> orderInfoCollection = carstore.getOrderInfoCollection();
			for (OrderInfo orderInfoCollectionOrderInfo : orderInfoCollection) {
				orderInfoCollectionOrderInfo.setStoreId(null);
				orderInfoCollectionOrderInfo = em.merge(orderInfoCollectionOrderInfo);
			}
			Collection<StoreInfo> storeInfoCollection = carstore.getStoreInfoCollection();
			for (StoreInfo storeInfoCollectionStoreInfo : storeInfoCollection) {
				storeInfoCollectionStoreInfo.setStoreId(null);
				storeInfoCollectionStoreInfo = em.merge(storeInfoCollectionStoreInfo);
			}
			em.remove(carstore);
			em.getTransaction().commit();
		} finally {
			if (em != null) {
				em.close();
			}
		}
	}

	public List<Carstore> findCarstoreEntities() {
		return findCarstoreEntities(true, -1, -1);
	}

	public List<Carstore> findCarstoreEntities(int maxResults, int firstResult) {
		return findCarstoreEntities(false, maxResults, firstResult);
	}

	private List<Carstore> findCarstoreEntities(boolean all, int maxResults, int firstResult) {
		EntityManager em = getEntityManager();
		try {
			CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
			cq.select(cq.from(Carstore.class));
			Query q = em.createQuery(cq);
			if (!all) {
				q.setMaxResults(maxResults);
				q.setFirstResult(firstResult);
			}
			return q.getResultList();
		} finally {
			em.close();
		}
	}

	public Carstore findCarstore(Integer id) {
		EntityManager em = getEntityManager();
		try {
			return em.find(Carstore.class, id);
		} finally {
			em.close();
		}
	}

	public int getCarstoreCount() {
		EntityManager em = getEntityManager();
		try {
			CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
			Root<Carstore> rt = cq.from(Carstore.class);
			cq.select(em.getCriteriaBuilder().count(rt));
			Query q = em.createQuery(cq);
			return ((Long) q.getSingleResult()).intValue();
		} finally {
			em.close();
		}
	}
	
}
